#include "main.h"

/*
#include "translations.h"

iconfigedit pbivce[] = {
	{ CFG_INFO, NULL, GetLangText("@Conf_def_info"), NULL, NULL, NULL, NULL, NULL },
	{ CFG_INDEX, NULL, GetLangText("@Zoom"), GetLangText("@Default_zoom_hint"), "layout_mode", "0", layout_variants, NULL },
	{ CFG_INDEX, NULL, GetLangText("@Fine_update"), GetLangText("Fine_update_hint"), "do_fine_update", "0", fine_update_variants, NULL },
	{ CFG_INFO, NULL, GetLangText("@Conf_sys_info"), NULL, NULL, NULL, NULL, NULL },
	{ CFG_TEXT, NULL, GetLangText("@Unrar_path"), GetLangText("@Unrar_path_hint"), "unrar_path", "/mnt/ext1/system/bin/unrar", NULL, NULL },
	{ CFG_TEXT, NULL, GetLangText("@Unzip_path"), GetLangText("@Unrar_path_hint"), "unzip_path", "/mnt/ext1/system/bin/unzip", NULL, NULL },
	{ 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};

void conf_handler() {
	SaveConfig(pbivcfg);
	draw();
}

void read_config() {
	iconfig *gcfg = GetGlobalConfig();
	lang = ReadString(gcfg, "language", "en");
	CloseConfig(gcfg);

	pbivcfg = OpenConfig(PBIVCFGFILE, pbivce);
	layout_mode = ReadInt(pbivcfg, "layout_mode", LAYOUT_DEFAULT);
	do_fine_update = ReadInt(pbivcfg, "do_fine_update", 0) != 0;
	mng.SetUnrarPath(ReadString(pbivcfg, "unrar_path", "/mnt/ext1/system/bin/unrar"));
	mng.SetUnzipPath(ReadString(pbivcfg, "unzip_path", "/mnt/ext1/system/bin/unzip"));
}

void save_config() {
	CloseConfig(pbivcfg);
}

imenu layout_menu[] = {
	{ ITEM_ACTIVE,  200+LAYOUT_DEFAULT, GetLangText("@Fit_default"), NULL },
	{ ITEM_ACTIVE,  200+LAYOUT_FIT_PAGE, GetLangText("@Fit_page"), NULL },
	{ ITEM_ACTIVE,  200+LAYOUT_FIT_HEIGHT, GetLangText("@Fit_height"), NULL },
	{ ITEM_ACTIVE,  200+LAYOUT_FIT_WIDTH, GetLangText("@Fit_width"), NULL },
	{ ITEM_ACTIVE,  200+LAYOUT_FULL_SIZE, GetLangText("@Full_size"), NULL },
	{ 0, 0, NULL, NULL }
};

imenu menu[] = {
	{ ITEM_HEADER,    0, GetLangText("@Menu"), NULL },
	{ ITEM_ACTIVE,  100, GetLangText("@Goto_page"), NULL },
	{ ITEM_SUBMENU,   0, GetLangText("@Zoom"), layout_menu },
	{ ITEM_ACTIVE,  300, GetLangText("@Fine_updates"), NULL },
	{ ITEM_ACTIVE,  400, GetLangText("@Configuration"), NULL },
	{ ITEM_ACTIVE,  500, GetLangText("@Help"), NULL },
	{ ITEM_ACTIVE,  600, GetLangText("@Exit"), NULL },
	{ 0, 0, NULL, NULL }
};

void pageselect_handler(int pagenum) {
	if (pagenum < 1)
	 pagenum = 1;
	else if (pagenum > (int)mng.GetFilesCount())
		pagenum = mng.GetFilesCount();
	v.SetImage(mng.GoTo(pagenum-1));
	draw();
}

void contents_handler(long long pos) {
	pageselect_handler((int)pos+1);
}

void update_fitmode() {
	switch (layout_mode) {
		case LAYOUT_DEFAULT:
			if (GetOrientation() == 0 || GetOrientation() == 3)  //Portrait
				v.SetFitMode(FIT_BOTH);
			else                         //Landscape
				v.SetFitMode(FIT_WIDTH);
			break;
		case LAYOUT_FIT_PAGE:
			v.SetFitMode(FIT_BOTH);
			break;
		case LAYOUT_FIT_HEIGHT:
			v.SetFitMode(FIT_HEIGHT);
			break;
		case LAYOUT_FIT_WIDTH:
			v.SetFitMode(FIT_WIDTH);
			break;
		case LAYOUT_FULL_SIZE:
			v.SetFitMode(FIT_NOT);
			break;
	}
}

void menu_handler(int index) {
	lastmenuindex = index;

	switch (index) {
		case 100:
			OpenPageSelector(pageselect_handler);
			break;
		case 200+LAYOUT_DEFAULT:
		case 200+LAYOUT_FIT_PAGE:
		case 200+LAYOUT_FIT_HEIGHT:
		case 200+LAYOUT_FIT_WIDTH:
		case 200+LAYOUT_FULL_SIZE:
			if (index-200 != layout_mode) {
				layout_mode = index - 200;
				update_fitmode();
				v.SetImage(mng.Current());
				draw();
			}
			break;
		case 300:
			do_fine_update = !do_fine_update;
			break;
		case 400:
			OpenConfigEditor(GetLangText("@Conf_title"), pbivcfg, pbivce, conf_handler, NULL);
			break;
		case 500:
			show_help();
			break;
		case 600:
			CloseApp();
			break;
		default:
			break;
	}
}

void apply_settings() {
	Settings settings;
	char *settings_file = GetAssociatedFile(have_archive ? (char*)infile.c_str() : (char*)dirbuff, 0);	
	Log::msg("settings file = %s\n", settings_file);
	FILE *fp = fopen(settings_file, "rb");
	if (fp &&
	    (fread(&settings, 1, sizeof(settings), fp) == sizeof(settings)) &&
	    settings.magic == 0x9751) {
		layout_mode = settings.layout_mode;
		update_fitmode();
		do_fine_update = settings.do_fine_update != 0;
		v.SetImage(mng.GoTo(settings.page));
		fclose(fp);
	} else
		v.SetImage(mng.Current());
}

void save_settings() {
	Settings settings;
	char *settings_file = GetAssociatedFile(have_archive ? (char*)infile.c_str() : (char*)dirbuff, 0);	
	settings.magic = 0x9751;
	settings.page = mng.GetCurrentFileIndex();
	settings.layout_mode = layout_mode;
	settings.do_fine_update = do_fine_update ? 1 : 0;
	FILE *fp = fopen(settings_file, "wb");
	if (fp) {
		fwrite(&settings, 1, sizeof(settings), fp);
		fclose(fp);
	}
}

void create_toc() {
	int numpages = mng.GetFilesCount();
	if ((toc = (tocentry*)malloc(numpages * sizeof(tocentry)))) {
		for (int i = 0; i < numpages; i++) {
			toc[i].level = 1;
			toc[i].page = i+1;
			toc[i].position = i;
			toc[i].text = (char*)mng.GetFileName(i).c_str();
		}
	}
	Log::msg("numpages = %d", numpages);
}
*/

void dir_selected(char *path) {
	std::string dir(path);
	if(!dir.empty())
	{
		strcpy(dirbuff,path);
		mng.Open(dir,"");

/*
		apply_settings();
		create_toc();
*/
		v.SetImage(mng.Current());

		draw();
	}
}

/*
bool open_archive() {
	have_archive = mng.IsSupportedArchive(infile);

	if (have_archive) {
		ShowHourglass();
		mng.Open(infile);
		apply_settings();
		HideHourglass();
		create_toc();
		draw();
	}

	return have_archive;
}

void draw_pagemap() {
	unsigned int margin = 4;  //Add this so icon moves away from right edge.
	unsigned short width = 12;
	unsigned short height = 18;
	unsigned short depth = 8;
	unsigned short scanline = (width + margin) * depth/8;

	int x, y, X, Y;
	double scaleX, scaleY;
	
	if (!pagemap) {
		pagemap = (ibitmap*)malloc(sizeof(ibitmap) + scanline*height);
		pagemap->width = width + margin;
		pagemap->height = height;
		pagemap->depth = depth;
		pagemap->scanline = scanline;
		memset(pagemap->data, 0x55, scanline*height);
	}

	irect imgr = v.GetImageRect();
	irect clipr = v.GetClipRect();

	scaleX = imgr.w / width;
	scaleY = imgr.h / height;
	for (y = 0; y < height; y++) {
		Y = (int)((y + 0.5) * scaleY + 0.5) + imgr.y;
		for (x = 0; x < width; x++) {
			X = (int)((x + 0.5) * scaleX + 0.5) + imgr.x;
			if (X<clipr.x || X>=(clipr.x+clipr.w) || Y<clipr.y || Y>=(clipr.y+clipr.h))
				pagemap->data[y*scanline+x+margin] = 255;
		  else
				pagemap->data[y*scanline+x+margin] = 0;
		}
	}
}

void get_new_translations() {
	trans_t *t = NULL;

	// Add new translations here after creating the trans_XX
	// array in translations.h
	if      (lang == "en") t = trans_en;
	//else if (lang == "ua") t = trans_ua;
	else                   t = trans_en;

	while (t->label) {
		AddTranslation(t->label, t->trans);
		t++;
	}
}

void add_def(std::string &msg, const char *key_label, const char *def_label) {
	msg += "\n";
	msg += GetLangText((char*)key_label);
	msg += ": ";
	msg += GetLangText((char*)def_label);
}

void show_help() {
	std::string msg = GetLangText("@Help_title");
	msg += "\n====================";
	add_def(msg, "@Key_ok", "@KA_mmnu");
	add_def(msg, "@Key_menu", "@Contents");
	add_def(msg, "@Key_next", "@KA_pgdn");
	add_def(msg, "@Key_plus", "@KA_pgdn");
	add_def(msg, "@Key_prev", "@KA_pgup");
	add_def(msg, "@Key_minus", "@KA_pgup");
	add_def(msg, "@Key_back", "@Help_back");
	add_def(msg, "@Key_left", "@Help_left");
	add_def(msg, "@Key_right", "@Help_right");
	add_def(msg, "@Key_up", "@Help_up");
	add_def(msg, "@Key_down", "@Help_down");
	add_def(msg, "@Key_zoomin", "@KA_zmin");
	add_def(msg, "@Key_up_h", "@KA_zmin");
	add_def(msg, "@Key_zoomout", "@KA_zout");
	add_def(msg, "@Key_down_h", "@KA_zout");
	msg += "\n\n";
	msg += GetLangText("@Translation_by");
	Dialog(ICON_INFORMATION, GetLangText("@Program_name"), (char*)msg.c_str(), GetLangText("@Close"), NULL, NULL);
}
*/

void draw()
{
	ClearScreen();
	v.Draw();
	Log::msg("Index: %d, size: %d, file: %s", mng.GetCurrentFileIndex(), mng.GetFilesCount(),
			mng.GetCurrentFileFullname().c_str());
	char buff[64];
	sprintf(buff, "%d/%d - %.0f%%", mng.GetCurrentFileIndex() + 1, mng.GetFilesCount(), v.GetScale() * 100);
/*
	if (mng.GetFilesCount() == 0)
		DrawPanel((ibitmap*)pagemap, buff, (char*) mng.GetCurrentFileName().c_str(), -1);
	else {
		draw_pagemap();
		DrawPanel((ibitmap*)pagemap, buff, (char*) mng.GetCurrentFileName().c_str(), -1);
	}
*/
	DrawPanel(NULL, buff, (char*) mng.GetCurrentFileName().c_str(), -1);

	FullUpdate();
/*
	if (do_fine_update)
*/
		FineUpdate();
}

int main_handler(int type, int par1, int par2)
{

	Log::msg("[%i %i %i]", type, par1, par2);

	if (type == EVT_INIT)
	{
/*
		read_config();
		get_new_translations();
		update_fitmode();
*/
		v.SetFitMode(FIT_BOTH);

		v.SetMoveStep(.75);
		v.SetClipRect(0, 0, ScreenWidth(), ScreenHeight() - PanelHeight());
		draw();
/*
		if (infile.empty() || !open_archive())
*/
			OpenDirectorySelector(GetLangText("@Open_dir"),dirbuff, 1024, dir_selected);
	}

	if (type == EVT_SHOW)
	{
		if (mng.Current()) {
			v.SetImage(mng.Current());
			draw();
		}
	}

	if (type == EVT_KEYRELEASE && par2 == 0)
	{
		switch (par1)
		{
		case KEY_OK:
			Log::msg("Key OK click");
/*
			OpenMenu(menu, lastmenuindex, 20, 20, menu_handler);
*/
			break;

		case KEY_BACK:
			Log::msg("Key Back click");
/*
			step_divisor <<= 1;
*/
			break;

		case KEY_LEFT:
			Log::msg("Key Left click");
/*
			if (step_divisor != 1)
				v.SetMoveStep(v.GetMoveStep()/step_divisor);
*/
			if (v.CanMoveDirection(DIRECTION_HORIZONTAL))
			{
				if (v.CanMoveDirection(DIRECTION_LEFT))
				{
					v.MoveDirection(DIRECTION_LEFT);
					draw();
				}
			}
			else
			{
				if (mng.HasPrev())
				{
					v.SetImage(mng.Prev());
					draw();
				}
			}
/*
			if (step_divisor != 1) {
				v.SetMoveStep(v.GetMoveStep()*step_divisor);
				step_divisor = 1;
			}
*/
			break;

		case KEY_RIGHT:
			Log::msg("Key Right click");
/*
			if (step_divisor != 1)
				v.SetMoveStep(v.GetMoveStep()/step_divisor);
*/
			if (v.CanMoveDirection(DIRECTION_HORIZONTAL))
			{
				if (v.CanMoveDirection(DIRECTION_RIGHT))
				{
					v.MoveDirection(DIRECTION_RIGHT);
					draw();
				}
			}
			else
			{
				if (mng.HasNext())
				{
					v.SetImage(mng.Next());
					draw();
				}
			}
/*
			if (step_divisor != 1) {
				v.SetMoveStep(v.GetMoveStep()*step_divisor);
				step_divisor = 1;
			}
*/
			break;

		case KEY_UP:
			Log::msg("Key Up click");
/*
			if (step_divisor != 1)
				v.SetMoveStep(v.GetMoveStep()/step_divisor);
*/
			if (v.CanMoveDirection(DIRECTION_VERTICAL))
			{
				if (v.CanMoveDirection(DIRECTION_UP))
				{
					v.MoveDirection(DIRECTION_UP);
					draw();
				}
			}
			else
			{
				if (mng.HasPrev())
				{
					v.SetImage(mng.Prev());
					draw();
				}
			}
/*
			if (step_divisor != 1) {
				v.SetMoveStep(v.GetMoveStep()*step_divisor);
				step_divisor = 1;
			}
*/
			break;

		case KEY_DOWN:
			Log::msg("Key Down click");
/*
			if (step_divisor != 1)
				v.SetMoveStep(v.GetMoveStep()/step_divisor);
*/
			if (v.CanMoveDirection(DIRECTION_VERTICAL))
			{
				if (v.CanMoveDirection(DIRECTION_DOWN))
				{
					v.MoveDirection(DIRECTION_DOWN);
					draw();
				}
			}
			else
			{
				if (mng.HasNext())
				{
					v.SetImage(mng.Next());
					draw();
				}
			}
/*
			if (step_divisor != 1) {
				v.SetMoveStep(v.GetMoveStep()*step_divisor);
				step_divisor = 1;
			}
*/
			break;

		case KEY_MINUS:
		case KEY_PREV:
			Log::msg("Key Prev (Minus) click");
			if (mng.HasPrev())
			{
				v.SetImage(mng.Prev());
				draw();
			}
			break;

		case KEY_PLUS:
		case KEY_NEXT:
			Log::msg("Key Next (Plus) click");
			if (mng.HasNext())
			{
				v.SetImage(mng.Next());
				draw();
			}
			break;

/*
#ifdef KEY_ZOOMIN
		case KEY_ZOOMIN:
			Log::msg("Key Zoomin click");
			if (v.CanZoomIn())
			{
				v.ZoomIn();
				draw();
			}
			break;
#endif

#ifdef KEY_ZOOMOUT
		case KEY_ZOOMOUT:
			Log::msg("Key Zoomout click");
			if (v.CanZoomOut())
			{
				v.ZoomOut();
				draw();
			}
			break;
#endif
*/
		case KEY_MENU:
			Log::msg("Key Menu click");
/*
			OpenContents(toc, mng.GetFilesCount(), mng.GetCurrentFileIndex(), contents_handler);
*/
			break;
		}
		if (!mng.IsBuffered())
			mng.Buffering();
	}
	if (type == EVT_KEYREPEAT && par2 == 1)
	{
		switch (par1)
		{
		case KEY_OK:
			Log::msg("Key OK hold");
			break;

		case KEY_LEFT:
			Log::msg("Key Left hold");
			break;

		case KEY_RIGHT:
			Log::msg("Key Right hold");
			break;

		case KEY_UP:
			Log::msg("Key Up hold");
			if (v.CanZoomIn())
			{
				v.ZoomIn();
				draw();
			}
			break;

		case KEY_DOWN:
			Log::msg("Key Down hold");
			if (v.CanZoomOut())
			{
				v.ZoomOut();
				draw();
			}
			break;

		case KEY_MINUS:
		case KEY_PREV:
			Log::msg("Key Prev (Minus) hold");

			break;

		case KEY_PLUS:
		case KEY_NEXT:
			Log::msg("Key Next (Plus) hold");

			break;

		case KEY_BACK:
			CloseApp();
			break;
		}
	}
/*
	if (type == EVT_ORIENTATION) {
		if (GetOrientation() != par1) {
			SetOrientation(par1);
			update_fitmode();
			v.SetClipRect(0, 0, ScreenWidth(), ScreenHeight() - PanelHeight());
			v.SetImage(mng.Current());
			draw();
		}
	}
*/
	if (type == EVT_EXIT)
	{
		// occurs only in main handler when exiting or when SIGINT received.
		// save configuration here, if needed
/*
		save_config();
		save_settings();
		if (have_archive)
			mng.DeleteUnpackedArchive();
		free(toc);
*/
	}

	return 0;

}

int main(int argc, char **argv)
{
/*
	if (argc == 2)
		infile = argv[1];
	else
		infile.erase();
*/

	InkViewMain(main_handler);
	return 0;
}
